/**
 ****************************************************************************************************
 * @file        my_2D.c
 * @author      嵌入式小书虫
 * @version     V1.0
 * @date        2020-04-17
 * @brief       my2d 驱动代码
 ****************************************************************************************************
 *
 * 修改说明
 * V1.0 20200417
 * 第一次发布
 <欢迎关注微信公众号：嵌入式小书虫>
 *
 ****************************************************************************************************
 */

#include "my_2D.h"
#include "my_2D_test.h"
//#include "my_2D_test.h"
#include "my_2D_draw.h"
my2D_scene_t my_scene;

my_2D_op_t my_2D_op;


void my2d_init(){ // 初始化 my-2d
    my_2D_op.state = 0;	
    my_2D_op.scene = &my_scene;
    
    //my_2D_op.pfb_size.iWidth = PFB_WIDTH;
    //my_2D_op.pfb_size.iHeight = PFB_HEIGHT;
    my_2D_op.pfb_region.tSize.iWidth = PFB_WIDTH;
    my_2D_op.pfb_region.tSize.iHeight = PFB_HEIGHT;
    
    my_2D_op.background_draw_flag = 0;

#if DIRTY_REGIONS_ENABLE      
    my_2D_op.DirtyRegions_num = 0;
    my_2D_op.DirtyRegions_run_num = 0;
#endif    
    
}

void my2d_disp_adapter0_task(){
    
    __my2d_disp_adapter0_task();
    
}

my2d_fsm_rt_t __my2d_disp_adapter0_task(void){
    return my2d_scene_player_task();
}

my2d_fsm_rt_t my2d_draw_all_screen(){
    my2d_Disp0_DrawBitmap (my_2D_op.pfb_region.tLocation.iX, 
             my_2D_op.pfb_region.tLocation.iY, 
             my_2D_op.pfb_region.tSize.iWidth, 
             my_2D_op.pfb_region.tSize.iHeight, 
             (uint8_t *)my_2D_op.pfb_data);

    my_2D_op.pfb_region.tLocation.iX +=  my_2D_op.pfb_region.tSize.iWidth;//   my_2D_op.pfb_size.iWidth;
    if(my_2D_op.pfb_region.tLocation.iX >= LCD_WIDTH){
        my_2D_op.pfb_region.tLocation.iX = 0;                
        my_2D_op.pfb_region.tLocation.iY += my_2D_op.pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(my_2D_op.pfb_region.tLocation.iY >= LCD_HEIGHT){
            //my_2D_op.state = 0;	
            return my2D_fsm_rt_cpl;
        }
    } 
    return my2D_fsm_rt_on_going;
}

#if DIRTY_REGIONS_ENABLE  
void calculate_pfb_DirtyRegion(){
    //uint16_t num = PFB_SIZE / my_2D_op.ptDirtyRegions[0].tSize.iWidth;
    my_2D_op.pfb_region.tLocation.iX = my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iX;
    my_2D_op.pfb_region.tLocation.iY = my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY;
    //行优先
    if(my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iWidth > PFB_SIZE){
        my_2D_op.pfb_region.tSize.iWidth = PFB_SIZE;
        my_2D_op.pfb_region.tSize.iHeight = 1;
        my_2D_op.Row_priority_flag = 1;
    }else{
        my_2D_op.pfb_region.tSize.iWidth = my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iWidth;
        my_2D_op.pfb_region.tSize.iHeight =  PFB_SIZE / my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iWidth;
        my_2D_op.Row_priority_flag = 0;
    }
}

my2d_fsm_rt_t my2d_draw_DirtyRegion_screen0(void){
    //else{
        if((my_2D_op.pfb_region.tLocation.iY + my_2D_op.pfb_region.tSize.iHeight) > (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
            my_2D_op.pfb_region.tSize.iHeight = my_2D_op.pfb_region.tSize.iHeight - ((my_2D_op.pfb_region.tLocation.iY + my_2D_op.pfb_region.tSize.iHeight) - (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight));
        }
        my2d_Disp0_DrawBitmap (my_2D_op.pfb_region.tLocation.iX, 
                                 my_2D_op.pfb_region.tLocation.iY, 
                                 my_2D_op.pfb_region.tSize.iWidth, 
                                 my_2D_op.pfb_region.tSize.iHeight, 
                                 (uint8_t *)my_2D_op.pfb_data);
        
        my_2D_op.pfb_region.tLocation.iY += my_2D_op.pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(my_2D_op.pfb_region.tLocation.iY >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
            //my_2D_op.state = 0;	
            //return my2D_fsm_rt_cpl;
            my_2D_op.DirtyRegions_run_num++;
            if(my_2D_op.DirtyRegions_run_num >= my_2D_op.DirtyRegions_num){
                //my_2D_op.state = 0;	
                my_2D_op.DirtyRegions_run_num = 0;
                //calculate_pfb_DirtyRegion();  
                return my2D_fsm_rt_cpl;
            }                                            
            calculate_pfb_DirtyRegion();                                        
        }
    //}
    return my2D_fsm_rt_on_going;
}
my2d_fsm_rt_t my2d_draw_DirtyRegion_screen1(void){
    
    //if(1 == my_2D_op.Row_priority_flag){
        my2d_region_t RegionOut;
        my2d_region_intersect(  &my_2D_op.pfb_region ,
                                &my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num],
                                &RegionOut);
        my2d_Disp0_DrawBitmap (RegionOut.tLocation.iX, 
             RegionOut.tLocation.iY, 
             RegionOut.tSize.iWidth, 
             RegionOut.tSize.iHeight, 
             (uint8_t *)my_2D_op.pfb_data);
        
        my_2D_op.pfb_region.tLocation.iX +=  my_2D_op.pfb_region.tSize.iWidth;//   my_2D_op.pfb_size.iWidth;
        if(my_2D_op.pfb_region.tLocation.iX >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iX 
                                                    + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iWidth)){
            my_2D_op.pfb_region.tLocation.iX = my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iX ;                
            my_2D_op.pfb_region.tLocation.iY += my_2D_op.pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
            if(my_2D_op.pfb_region.tLocation.iY >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                    + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
                //my_2D_op.state = 0;	
                //return my2D_fsm_rt_cpl;
                my_2D_op.DirtyRegions_run_num++;
                if(my_2D_op.DirtyRegions_run_num >= my_2D_op.DirtyRegions_num){
                    //my_2D_op.state = 0;	
                    my_2D_op.DirtyRegions_run_num = 0;
                    //calculate_pfb_DirtyRegion();  
                    return my2D_fsm_rt_cpl;
                }                                            
                calculate_pfb_DirtyRegion();                                        
            }
        }
    //}
    return my2D_fsm_rt_on_going;
}

typedef my2d_fsm_rt_t my2d_draw_DirtyRegion_screen_fn(void);
my2d_draw_DirtyRegion_screen_fn * const my2d_draw_DirtyRegion_screen_fn_num[2] = {
    &my2d_draw_DirtyRegion_screen0,
    &my2d_draw_DirtyRegion_screen1,
};
#endif

my2d_fsm_rt_t my2d_scene_player_task(){
    enum {
        START = 0,
        DRAW_FRAME_START,//绘图框开始
        DRAW_BACKGROUND_PREPARE,//绘制背景准备
        DRAW_BACKGROUND,//绘制背景
        DRAW_SCENE_PREPARE,//绘制场景准备
        DRAW_SCENE,//绘制场景
        POST_SCENE_CHECK,//现场后检查

        SWITCH_SCENE_PREPARE,//切换场景准备
        SWITCH_SCENE,//切换场景
        SWITCH_SCENE_POST,//切换场景桩
    };
    //static char flag = 0;
    switch(my_2D_op.state){
        case START:
#if DIRTY_REGIONS_ENABLE              
            if(my_2D_op.DirtyRegions_num){
                calculate_pfb_DirtyRegion();
            }else{
                my_2D_op.pfb_region.tLocation.iY = 0;
                my_2D_op.pfb_region.tLocation.iX = 0;
                my_2D_op.pfb_region.tSize.iWidth = PFB_WIDTH;
                my_2D_op.pfb_region.tSize.iHeight = PFB_HEIGHT;
            }
        
#else        
                my_2D_op.pfb_region.tLocation.iY = 0;
                my_2D_op.pfb_region.tLocation.iX = 0;
                my_2D_op.pfb_region.tSize.iWidth = PFB_WIDTH;
                my_2D_op.pfb_region.tSize.iHeight = PFB_HEIGHT;
#endif        

            //my_2D_op.state = DRAW_SCENE_PREPARE;
            //break;
            if(my_2D_op.background_draw_flag){
                my_2D_op.state = DRAW_SCENE_PREPARE;
                //break;
            }else{
                my_2D_op.pfb_region.tLocation.iY = 0;
                my_2D_op.pfb_region.tLocation.iX = 0;
                my_2D_op.pfb_region.tSize.iWidth = PFB_WIDTH;
                my_2D_op.pfb_region.tSize.iHeight = PFB_HEIGHT;
                my_2D_op.state = DRAW_BACKGROUND_PREPARE;//DRAW_BACKGROUND_PREPARE;
            }                
            //break;
        case  DRAW_BACKGROUND_PREPARE:
            if(0 == my_2D_op.background_draw_flag){
                my_2D_op.state = DRAW_BACKGROUND;
                
            }
        //break;
        case  DRAW_BACKGROUND:
            if(0 == my_2D_op.background_draw_flag){
                my_2D_op.scene->fnScene(my_2D_op.bIsNewFrame);
                if(my2D_fsm_rt_cpl == my2d_draw_all_screen()){
                    my_2D_op.state = DRAW_SCENE_PREPARE;
                    my_2D_op.background_draw_flag = 1;
#if DIRTY_REGIONS_ENABLE                      
                    if(my_2D_op.DirtyRegions_num){
                        calculate_pfb_DirtyRegion();
                    }
#endif                    
                }
            }
        break;
        case DRAW_SCENE_PREPARE:
            my_2D_op.scene->fnOnFrameStart(my_2D_op.scene);
            my_2D_op.state = DRAW_SCENE;	
            //break;
        case DRAW_SCENE:
             
            my_2D_op.scene->fnScene(my_2D_op.bIsNewFrame); 
#if DIRTY_REGIONS_ENABLE         
            if(my_2D_op.DirtyRegions_num){
                //my2d_draw_DirtyRegion_screen();//======================================
                if(my2D_fsm_rt_cpl == (*my2d_draw_DirtyRegion_screen_fn_num[my_2D_op.Row_priority_flag])()){
                    my_2D_op.state = 0;	
                }
            }else{
                if(my2D_fsm_rt_cpl == my2d_draw_all_screen()){
                    my_2D_op.state = 0;
                }
            }
#else
            if(my2D_fsm_rt_cpl == my2d_draw_all_screen()){
                my_2D_op.state = 0;
            }
#endif        
            break;
        case SWITCH_SCENE:
            my_2D_op.background_draw_flag = 0;
        break;
    }
    return my2D_fsm_rt_on_going;
}



void my2d_Disp0_DrawBitmap (uint32_t x, 
                            uint32_t y, 
                            uint32_t width, 
                            uint32_t height, 
                            const uint8_t *bitmap) 
{
    lcd_color_fill(x, y,  width ,  height , (uint16_t *)bitmap);
}

//=====================================================
#if 0
my2d_fsm_rt_t my2d_draw_DirtyRegion_screen(){
    
    if(1 == my_2D_op.Row_priority_flag){
        my2d_region_t RegionOut;
        my2d_region_intersect(  &my_2D_op.pfb_region ,
                                &my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num],
                                &RegionOut);
        my2d_Disp0_DrawBitmap (RegionOut.tLocation.iX, 
             RegionOut.tLocation.iY, 
             RegionOut.tSize.iWidth, 
             RegionOut.tSize.iHeight, 
             (uint8_t *)my_2D_op.pfb_data);
        
        my_2D_op.pfb_region.tLocation.iX +=  my_2D_op.pfb_region.tSize.iWidth;//   my_2D_op.pfb_size.iWidth;
        if(my_2D_op.pfb_region.tLocation.iX >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iX 
                                                    + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iWidth)){
            my_2D_op.pfb_region.tLocation.iX = my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iX ;                
            my_2D_op.pfb_region.tLocation.iY += my_2D_op.pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
            if(my_2D_op.pfb_region.tLocation.iY >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                    + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
                //my_2D_op.state = 0;	
                //return my2D_fsm_rt_cpl;
                my_2D_op.DirtyRegions_run_num++;
                if(my_2D_op.DirtyRegions_run_num >= my_2D_op.DirtyRegions_num){
                    my_2D_op.state = 0;	
                    my_2D_op.DirtyRegions_run_num = 0;
                    //calculate_pfb_DirtyRegion();  
                    return my2D_fsm_rt_cpl;
                }                                            
                calculate_pfb_DirtyRegion();                                        
            }
        }
    }else{
        if((my_2D_op.pfb_region.tLocation.iY + my_2D_op.pfb_region.tSize.iHeight) > (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
            my_2D_op.pfb_region.tSize.iHeight = my_2D_op.pfb_region.tSize.iHeight - ((my_2D_op.pfb_region.tLocation.iY + my_2D_op.pfb_region.tSize.iHeight) - (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight));
        }
        my2d_Disp0_DrawBitmap (my_2D_op.pfb_region.tLocation.iX, 
                                 my_2D_op.pfb_region.tLocation.iY, 
                                 my_2D_op.pfb_region.tSize.iWidth, 
                                 my_2D_op.pfb_region.tSize.iHeight, 
                                 (uint8_t *)my_2D_op.pfb_data);
        
        my_2D_op.pfb_region.tLocation.iY += my_2D_op.pfb_region.tSize.iHeight; //my_2D_op.pfb_size.iHeight;
        if(my_2D_op.pfb_region.tLocation.iY >= (my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tLocation.iY 
                                                + my_2D_op.ptDirtyRegions[my_2D_op.DirtyRegions_run_num].tSize.iHeight)){
            //my_2D_op.state = 0;	
            //return my2D_fsm_rt_cpl;
            my_2D_op.DirtyRegions_run_num++;
            if(my_2D_op.DirtyRegions_run_num >= my_2D_op.DirtyRegions_num){
                my_2D_op.state = 0;	
                my_2D_op.DirtyRegions_run_num = 0;
                //calculate_pfb_DirtyRegion();  
                return my2D_fsm_rt_cpl;
            }                                            
            calculate_pfb_DirtyRegion();                                        
        }
    }
    return my2D_fsm_rt_on_going;
}
#endif
